﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WinCourseControls.UControls
{
    /// <summary>
    /// 自定义控件
    /// </summary>
    [DefaultEvent("BtnClick")] // 设置指定组件的默认事件
    public class MyButton:Control
    {
        /// <summary>
        /// 自定义button按钮初始化
        /// </summary>
        public MyButton()
        {
            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);  // 忽略窗口消息减少闪烁
            this.SetStyle(ControlStyles.UserPaint, true); // 设置不是由操作系统来绘制控件自身
            this.SetStyle(ControlStyles.DoubleBuffer, true); // 设置在缓冲区绘制，完成后再显示到页面-双缓冲可以防止因重绘控件而引起的闪烁。
            this.SetStyle(ControlStyles.ResizeRedraw, true);  // 调整大小时重绘控件
            this.SetStyle(ControlStyles.Selectable, true); // 设置控件可以接受焦点
            this.SetStyle(ControlStyles.SupportsTransparentBackColor, true); // 支持控件设置透明色
            this.Size = new Size(80, 30); // 设置控件初始大小
        }

        /// <summary>
        /// 按钮点击事件
        /// </summary>
        public event EventHandler BtnClick;//单击事件

        private string btnText;
        /// <summary>
        /// 按钮文本属性
        /// </summary>
        public string BtnText
        {
            get { return btnText; }
            set { btnText = value;
                Refresh(); // 触发控件重绘事件
            }
        }

        private Color bColor = Color.Gray;
        /// <summary>
        /// 边框颜色属性
        /// </summary>
        public Color BColor
        {
            get { return bColor; }
            set
            {
                bColor = value;
                Refresh(); // 触发控件重绘事件
            }
        }

        private Color bgColor = Color.White;
        /// <summary>
        /// 背景色属性
        /// </summary>
        public Color BgColor
        {
            get { return bgColor; }
            set
            {
                bgColor = value;
                Refresh(); // 触发控件重绘事件
            }
        }

        private int borderWidth = 2;
        /// <summary>
        /// 边框粗细属性
        /// </summary>
        public int BorderWidth
        {
            get { return borderWidth; }
            set
            {
                borderWidth = value;
                Refresh(); // 触发控件重绘事件
            }
        }
        private Color _enterBColor = Color.Red;
        /// <summary>
        /// 鼠标移入控件边框颜色
        /// </summary>
        public Color EnterBColor
        {
            get { return _enterBColor; }
            set
            {
                _enterBColor = value;
            }
        }

        private Color _enterBgColor = Color.Blue;
        /// <summary>
        /// 鼠标移入控件背景色
        /// </summary>
        public Color EnterBgColor
        {
            get { return _enterBgColor; }
            set
            {
                _enterBgColor = value;
            }
        }

        /// <summary>
        /// 鼠标移出控件边框颜色
        /// </summary>
        private Color _deBColor;
        /// <summary>
        /// 鼠标移出控件背景色
        /// </summary>
        private Color _deBgColor;

        /// <summary>
        /// 鼠标进入控件时发生
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseEnter(EventArgs e)
        {
            base.OnMouseEnter(e);  // 重绘事件必须要出发父类的这个方法
            _deBColor = BColor; // 暂存之前的边框颜色
            _deBgColor = BgColor; // 暂存鼠标移入前的背景色
            BColor = EnterBColor; // 设置鼠标移入后的边框颜色
            BgColor = EnterBgColor; // 设置鼠标移入后的背景色
        }

        /// <summary>
        /// 鼠标按下边框颜色
        /// </summary>
        private Color _downBColor = Color.Purple;
        /// <summary>
        /// 鼠标按下边框颜色
        /// </summary>
        public Color DownBColor
        {
            get { return _downBColor; }
            set
            {
                _downBColor = value;
            }
        }

        /// <summary>
        /// 鼠标按下边框背景色
        /// </summary>
        private Color _downBgColor = Color.DarkRed;
        /// <summary>
        /// 鼠标按下边框背景色
        /// </summary>
        public Color DownBgColor
        {
            get { return _downBgColor; }
            set
            {
                _downBgColor = value;
            }
        }

        /// <summary>
        /// 鼠标按下标识
        /// </summary>
        bool isClick = false;

        /// <summary>
        /// 鼠标按下时发生
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);
            this.Focus(); // 鼠标按下为控件设置输入焦点
            BgColor = DownBgColor; // 设置鼠标按下边框颜色
            BColor = DownBColor; // 设置鼠标按下背景色
            if(BtnClick!=null)
            {   // 判断事件不为空
                isClick = true; // 鼠标按下
                BtnClick?.Invoke(this, new EventArgs()); // 鼠标按下时 - 如果事件不为null - 执行单击事件
                isClick = false;
            }
          
        }

        /// <summary>
        /// 鼠标离开控件时发生
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseLeave(EventArgs e)
        {
            base.OnMouseLeave(e);
            if(!this.Focused&&!isClick) // 判断控件是否获取焦点
            { // 控件没有获取焦点
                BgColor = _deBgColor; // 恢复暂存的边框颜色
                BColor = _deBColor; // 恢复暂存的背景色
            }
            else
            {  // 控件有获取到焦点
                BColor = DownBColor; // 设置边框颜色保持按下时颜色
                BgColor = _deBgColor; // 设置背景色恢复默认背景色 - 也可以设置其它颜色
            }
        }

        /// <summary>
        /// 控件失去焦点时发生
        /// </summary>
        /// <param name="e"></param>
        protected override void OnLostFocus(EventArgs e)
        {
            base.OnLostFocus(e); // 重写事件需要执行的方法
            if (!this.Focused&&!isClick)
            {  // !this.Focused 控件没有获取焦点  !isClick 鼠标没有按下
                BgColor = _deBgColor; // 恢复暂存的边框颜色
                BColor = _deBColor; // 恢复暂存的背景色
            }
            else
            { // 控件有焦点 或者 鼠标按下了
                BColor = DownBColor; // 设置边框颜色保持按下时颜色
                BgColor = _deBgColor; // 设置背景色恢复默认背景色 - 也可以设置其它颜色
            }
        }

        /// <summary>
        /// 外观绘制-画控件
        /// </summary>
        /// <param name="e"></param>
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            Graphics g = e.Graphics; // 绘图对象
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;//呈现质量
            g.Clear(this.Parent.BackColor); // 清空原有背景-以父容器的背景色进行填充-这样在重绘控件时相当于透明色

            Rectangle rect = new Rectangle(); // 边框区域实例
            if (BorderWidth > 0) // 边框粗细判断
            {  // 设置边框粗细 
                rect.X = BorderWidth - 1; // 边框粗细 - 1
                rect.Y = BorderWidth - 1; // 边框粗细 - 1
                rect.Width = this.ClientRectangle.Width - BorderWidth * 2 + 1; // 工作区域宽度 - 边框粗细*2+1
                rect.Height = this.ClientRectangle.Height - BorderWidth * 2 + 1; // 工作区域高度 - 边框粗细*2+1
            }
            else // 没有设置边框粗细
            { // 矩形区域恢复默认
                rect.X = 0;
                rect.Y = 0;
                rect.Width = this.ClientRectangle.Width;
                rect.Height = this.ClientRectangle.Height;
            }
            g.FillEllipse(new SolidBrush(this.BgColor), rect);//按钮背景画好 - 填充矩形的背景色
            if(BorderWidth>0) // 边框粗细判断
            {
                g.DrawEllipse(new Pen(this.BColor, BorderWidth), rect);//画椭圆边框
            }
            //绘制文本
            //文字对齐方式
            StringFormat f = new StringFormat();
            f.Alignment = StringAlignment.Center; // 设置文本水平对齐
            f.LineAlignment = StringAlignment.Center; // 设置文本垂直对齐
            g.DrawString(this.BtnText, this.Font, new SolidBrush(this.ForeColor), rect, f); // 文本样式画好
        }
    }
}
